// Author: wsfuyibing <682805@qq.com>
// Date: 2025-04-11

package starter

import (
	"context"
	"gitee.com/go-libs/console"
	"gitee.com/go-wares/framework-gin/framework/application"
	"gitee.com/go-wares/framework-gin/framework/commands"
)

const (
	cmdDesc = "Start application with gin web framework"
	cmdName = "start"
)

var cmdOptions = map[string]*commands.Option{
	"port": {
		Description:  "Listen port, override config file setting",
		Kind:         console.KindInt,
		Required:     false,
		Short:        'p',
		DefaultValue: application.Application.AppConfig().Port,
	},
	"host": {
		Description: "Listen address, override config file setting",
		Kind:        console.KindString,
		Required:    false,
		Short:       'h',
	},
}

type Provider struct {
	common commands.Provider

	port int
	cmd  *console.Command
}

func (o *Provider) Before(_ context.Context, container *console.Container, cmd *console.Command) (err error) {
	// Replace listen host config.
	if opt, has := cmd.GetOption("host"); has {
		if str := opt.ToString(); str != "" {
			application.Application.AppConfig().Host = str
		}
	}

	// Replace listen port config.
	if opt, has := cmd.GetOption("port"); has {
		if n := opt.ToInt(); n > 0 {
			application.Application.AppConfig().Port = int(n)
		}
	}

	container.GetOutput().Info(`cmd.GetDescription()`)
	return
}

func (o *Provider) Run(ctx context.Context, _ *console.Container, _ *console.Command) (err error) {
	err = application.Application.Start(ctx)
	return
}

// +---------------------------------------------------------------------------+
// | Access methods                                                            |
// +---------------------------------------------------------------------------+

func (o *Provider) init() *Provider {
	o.cmd = console.NewCommand(cmdName).SetDescription(cmdDesc).SetProvider(o)
	o.initOptions()
	return o
}

func (o *Provider) initOptions() {
	for name, option := range cmdOptions {
		if option == nil {
			return
		}
		opt := console.NewOption(name).
			SetDescription(option.Description).
			SetKind(option.Kind).
			SetRequired(option.Required)
		if option.Short > 0 {
			opt.SetShortName(option.Short)
		}
		if option.DefaultValue != nil {
			opt.SetDefaultValue(option.DefaultValue)
		}
		o.cmd.Add(opt)
	}
}

func New() *console.Command {
	return (&Provider{}).init().cmd
}
